<!--
@license
Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<link rel="import" href="../iron-icon/iron-icon.html" />
<link rel="import" href="../paper-button/paper-button.html" />
<link rel="import" href="../paper-dropdown-menu/paper-dropdown-menu.html" />
<link rel="import" href="../paper-icon-button/paper-icon-button.html" />
<link rel="import" href="../paper-item/paper-item.html" />
<link rel="import" href="../paper-listbox/paper-listbox.html" />
<link rel="import" href="../paper-radio-group/paper-radio-group.html" />
<link rel="import" href="../paper-toggle-button/paper-toggle-button.html" />
<link rel="import" href="../paper-tooltip/paper-tooltip.html" />
<link rel="import" href="../tf-imports/polymer.html" />
<link rel="import" href="../tf-dashboard-common/tensorboard-color.html" />
<link rel="import" href="../tf-graph-common/tf-graph-common.html" />
<link rel="import" href="../tf-graph-common/tf-graph-icon.html" />
<link rel="import" href="../tf-graph-node-search/tf-graph-node-search.html" />

<dom-module id="tf-graph-controls">
  <template>
    <style>
      :host {
        color: gray;
        display: flex;
        flex-direction: column;
        font-size: 12px;
        width: 100%;
      }

      paper-dropdown-menu {
        --paper-dropdown-menu-input: {
          padding: 0;
          color: gray;
        }
        --iron-icon-width: 15px;
        --iron-icon-height: 15px;
        --primary-text-color: gray;
        --paper-item-min-height: 30px;
      }

      paper-button[raised].keyboard-focus {
        font-weight: normal;
      }

      .run-dropdown {
        --paper-input-container: {
          padding: 8px 0 8px 10px;
        }
      }

      .color-dropdown {
        --paper-input-container: {
          padding: 9px 0 0 13px;
        }
      }

      table {
        border-collapse: collapse;
        border-spacing: 0;
      }

      table td {
        padding: 0;
        margin: 0;
      }

      .allcontrols {
        padding: 0 20px 20px;
        flex-grow: 1;
        overflow-y: auto;
      }

      .legend-holder {
        background: #e9e9e9;
        border-top: 1px solid #ccc;
        box-sizing: border-box;
        color: #555;
        padding: 15px 20px;
        width: 100%;
      }

      .toggle-legend-button {
        max-height: 20px;
        max-width: 20px;
        padding: 0;
      }

      .toggle-legend-text {
        vertical-align: middle;
      }

      paper-radio-button {
        display: block;
        padding: 5px;
      }
      svg.icon,
      tf-graph-icon {
        width: 60px;
        height: 18px;
      }
      .domainValues {
        margin-bottom: 10px;
        width: 165px;
      }
      .domainStart {
        float: left;
      }
      .domainEnd {
        float: right;
      }
      .colorBox {
        width: 20px;
      }

      .image-icon {
        width: 24px;
        height: 24px;
      }

      .help-icon {
        height: 15px;
        margin: 0;
        padding: 0;
      }

      .gray {
        color: #666;
      }

      .title {
        font-size: 16px;
        margin: 8px 5px 8px 0;
        color: black;
      }
      .title small {
        font-weight: normal;
      }
      .deviceList,
      .xlaClusterList {
        max-height: 200px;
        overflow-y: auto;
      }

      #file {
        padding: 8px 0;
      }

      .color-legend-row {
        align-items: center;
        clear: both;
        display: flex;
        height: 20px;
        margin-top: 5px;
      }

      .color-legend-row .label,
      .color-legend-row svg,
      .color-legend-row tf-graph-icon {
        flex: 0 0 40px;
        margin-right: 20px;
      }

      .devices-checkbox input {
        text-align: left;
        vertical-align: middle;
      }

      .control-holder .icon-button {
        font-size: 14px;
        margin: 0 -5px;
        padding: 5px;
      }

      .button-text {
        padding-left: 20px;
        text-transform: none;
      }

      .upload-button {
        width: 165px;
        height: 25px;
        text-transform: none;
        margin-top: 4px;
      }

      .button-icon {
        width: 26px;
        height: 26px;
        color: var(--paper-orange-500);
      }

      .hidden-input {
        height: 0px;
        width: 0px;
        overflow: hidden;
      }

      .allcontrols .control-holder {
        clear: both;
        display: flex;
        justify-content: space-between;
      }

      .allcontrols .control-holder paper-radio-group {
        margin-top: 5px;
      }

      span.counter {
        font-size: 13px;
        color: gray;
      }

      .runs paper-item {
        --paper-item: {
          white-space: nowrap;
        }
      }

      table.control-holder {
        border: 0;
        border-collapse: collapse;
      }

      table.tf-graph-controls td.input-element-table-data {
        padding: 0 0 0 20px;
      }

      .spacer {
        flex-grow: 1;
      }

      .color-text {
        overflow: hidden;
      }

      /** Override inline styles that suppress pointer events for disabled buttons. Otherwise, the */
      /*  tooltips do not appear. */
      paper-radio-group paper-radio-button {
        pointer-events: auto !important;
      }

      .legend-clarifier {
        color: #266236;
        cursor: help;
        display: inline-block;
        text-decoration: underline;
      }

      .legend-clarifier paper-tooltip {
        width: 150px;
      }

      /** Otherwise, polymer UI controls appear atop node search. */
      tf-graph-node-search {
        z-index: 1;
        width: 100%;
      }

      paper-dropdown-menu {
        flex-grow: 1;
      }
    </style>

    <div class="allcontrols">
      <div class="control-holder">
        <tf-graph-node-search
          selected-node="{{selectedNode}}"
          render-hierarchy="[[renderHierarchy]]"
        ></tf-graph-node-search>
      </div>
      <div class="control-holder">
        <paper-button class="icon-button" on-tap="_fit" alt="Fit to screen">
          <iron-icon icon="aspect-ratio" class="button-icon"></iron-icon>
          <span class="button-text">Fit to Screen</span>
        </paper-button>
      </div>
      <div class="control-holder">
        <paper-button
          class="icon-button"
          on-click="download"
          alt="Download PNG"
        >
          <iron-icon icon="file-download" class="button-icon"></iron-icon>
          <span class="button-text">Download PNG</span>
        </paper-button>
        <a href="#" id="graphdownload" class="title" download="graph.png"></a>
      </div>
      <div class="control-holder runs">
        <div class="title">
          Run <span class="counter">([[datasets.length]])</span>
        </div>
        <paper-dropdown-menu
          no-label-float
          no-animations
          noink
          horizontal-align="left"
          class="run-dropdown"
        >
          <paper-listbox
            class="dropdown-content"
            selected="{{_selectedRunIndex}}"
            slot="dropdown-content"
          >
            <template is="dom-repeat" items="[[datasets]]">
              <paper-item>[[item.name]]</paper-item>
            </template>
          </paper-listbox>
        </paper-dropdown-menu>
      </div>
      <template is="dom-if" if="[[showSessionRunsDropdown]]">
        <div class="control-holder">
          <div class="title">
            Tag
            <span class="counter"
              >([[_numTags(datasets, _selectedRunIndex)]])</span
            >
          </div>
          <paper-dropdown-menu
            no-label-float
            no-animations
            horizontal-align="left"
            noink
            class="run-dropdown"
          >
            <paper-listbox
              class="dropdown-content"
              selected="{{_selectedTagIndex}}"
              slot="dropdown-content"
            >
              <template
                is="dom-repeat"
                items="[[_getTags(datasets, _selectedRunIndex)]]"
              >
                <paper-item>[[item.displayName]]</paper-item>
              </template>
            </paper-listbox>
          </paper-dropdown-menu>
        </div>
      </template>
      <template is="dom-if" if="[[showUploadButton]]">
        <div class="control-holder">
          <div class="title">Upload</div>
          <paper-button
            raised
            class="upload-button"
            on-click="_getFile"
            title="Upload a graph pbtxt file to view the graph"
          >
            Choose File
          </paper-button>
          <div class="hidden-input">
            <input
              type="file"
              id="file"
              name="file"
              on-change="_updateFileInput"
              accept=".pbtxt"
            />
          </div>
        </div>
      </template>
      <div class="control-holder">
        <paper-radio-group selected="{{_selectedGraphType}}">
          <!-- Note that the name has to match that of tf.graph.SelectionType. -->
          <paper-radio-button
            name="op_graph"
            disabled="[[_getSelectionOpGraphDisabled(datasets, _selectedRunIndex, _selectedTagIndex)]]"
            >Graph</paper-radio-button
          >
          <paper-radio-button
            name="conceptual_graph"
            disabled="[[_getSelectionConceptualGraphDisabled(datasets, _selectedRunIndex, _selectedTagIndex)]]"
            >Conceptual Graph</paper-radio-button
          >
          <paper-radio-button
            name="profile"
            disabled="[[_getSelectionProfileDisabled(datasets, _selectedRunIndex, _selectedTagIndex)]]"
            >Profile</paper-radio-button
          >
        </paper-radio-group>
      </div>
      <div class="control-holder">
        <div>
          <paper-toggle-button checked="{{traceInputs}}" class="title">
            Trace inputs
          </paper-toggle-button>
        </div>
      </div>
      <template is="dom-if" if="[[healthPillsFeatureEnabled]]">
        <div class="control-holder">
          <paper-toggle-button checked="{{healthPillsToggledOn}}" class="title"
            >Show health pills</paper-toggle-button
          >
        </div>
      </template>
      <div class="control-holder">
        <div class="title">Color</div>
        <paper-radio-group selected="{{colorBy}}">
          <paper-radio-button name="structure">Structure</paper-radio-button>

          <paper-radio-button name="device">Device</paper-radio-button>

          <paper-radio-button
            id="xla-cluster-radio-button"
            name="xla_cluster"
            disabled="[[!_xlaClustersProvided(renderHierarchy)]]"
          >
            XLA Cluster
          </paper-radio-button>
          <paper-tooltip
            animation-delay="0"
            for="xla-cluster-radio-button"
            position="right"
            offset="0"
          >
            Coloring by XLA cluster is only enabled if at least 1 op specifies
            an XLA cluster.
          </paper-tooltip>

          <paper-radio-button
            id="compute-time-radio-button"
            name="compute_time"
            disabled="[[!stats]]"
          >
            Compute time
          </paper-radio-button>
          <paper-tooltip
            animation-delay="0"
            for="compute-time-radio-button"
            position="right"
            offset="0"
          >
            Coloring by compute time is only enabled if the RunMetadata proto is
            passed to the FileWriter when a specific session is run.
          </paper-tooltip>

          <paper-radio-button
            id="memory-radio-button"
            name="memory"
            disabled="[[!stats]]"
          >
            Memory
          </paper-radio-button>
          <paper-tooltip
            animation-delay="0"
            for="memory-radio-button"
            position="right"
            offset="0"
          >
            Coloring by memory is only enabled if the RunMetadata proto is
            passed to the FileWriter when a specific session is run.
          </paper-tooltip>

          <paper-radio-button
            id="tpu-compatibility-radio-button"
            name="op_compatibility"
          >
            TPU Compatibility
          </paper-radio-button>
          <paper-tooltip
            animation-delay="0"
            for="tpu-compatibility-radio-button"
            position="right"
            offset="0"
          >
            Coloring by whether an operation is compatible for the TPU device.
          </paper-tooltip>
        </paper-radio-group>
        <span class="spacer"></span>
      </div>
      <div>
        <template is="dom-if" if="[[_isGradientColoring(stats, colorBy)]]">
          <svg width="140" height="20" style="margin: 0 5px" class="color-text">
            <defs>
              <linearGradient
                id="linearGradient"
                x1="0%"
                y1="0%"
                x2="100%"
                y2="0%"
              >
                <stop
                  class="start"
                  offset="0%"
                  stop-color$="[[_currentGradientParams.startColor]]"
                />
                <stop
                  class="end"
                  offset="100%"
                  stop-color$="[[_currentGradientParams.endColor]]"
                />
              </linearGradient>
            </defs>
            <rect
              x="0"
              y="0"
              width="135"
              height="20"
              fill="url(#linearGradient)"
              stroke="black"
            />
          </svg>
          <div class="domainValues color-text">
            <div class="domainStart">[[_currentGradientParams.minValue]]</div>
            <div class="domainEnd">[[_currentGradientParams.maxValue]]</div>
          </div>
          <br style="clear: both" />
          <div>Devices included in stats:</div>
          <div class="deviceList">
            <template is="dom-repeat" items="[[_currentDevices]]">
              <div class="color-legend-row devices-checkbox">
                <span
                  ><input
                    type="checkbox"
                    value$="[[item.device]]"
                    checked$="[[item.used]]"
                    on-click="_deviceCheckboxClicked"
                /></span>
                <span>[[item.suffix]]</span>
                <template is="dom-if" if="[[item.ignoredMsg]]">
                  <paper-icon-button
                    icon="help"
                    class="help-icon"
                  ></paper-icon-button>
                  <paper-tooltip position="right" offset="0" animation-delay="0"
                    >[[item.ignoredMsg]]</paper-tooltip
                  >
                </template>
              </div>
            </template>
          </div>
        </template>
        <template is="dom-if" if="[[_equals(colorBy, 'structure')]]">
          <div class="color-text">
            <div class="color-legend-row">
              <span class="label">
                colors
              </span>
              <span class="color-legend-value">same substructure</span>
            </div>
            <div class="color-legend-row">
              <tf-graph-icon
                type="META"
                height="16"
                fill-override="#eee"
                stroke-override="#a6a6a6"
              ></tf-graph-icon>
              <span class="color-legend-value">unique substructure</span>
            </div>
          </div>
        </template>
        <template is="dom-if" if="[[_equals(colorBy, 'device')]]">
          <div>
            <template is="dom-repeat" items="[[_currentDeviceParams]]">
              <div class="color-legend-row">
                <tf-graph-icon
                  type="META"
                  height="16"
                  fill-override="[[item.color]]"
                  stroke-override="#a6a6a6"
                ></tf-graph-icon>
                <span class="color-legend-value">[[item.device]]</span>
              </div>
            </template>
            <div class="color-legend-row">
              <tf-graph-icon
                type="META"
                height="16"
                fill-override="#eee"
                stroke-override="#a6a6a6"
              ></tf-graph-icon>
              <span class="color-legend-value">unknown device</span>
            </div>
          </div>
        </template>
        <template is="dom-if" if="[[_equals(colorBy, 'xla_cluster')]]">
          <div>
            <template is="dom-repeat" items="[[_currentXlaClusterParams]]">
              <div class="color-legend-row">
                <svg>
                  <use
                    xmlns:xlink="http://www.w3.org/1999/xlink"
                    xlink:href="#unfilled-rect"
                    x="0"
                    y="0"
                    style="fill:[[item.color]]"
                  />
                </svg>
                <span class="color-legend-value">[[item.xla_cluster]]</span>
              </div>
            </template>
            <div class="color-legend-row">
              <svg>
                <use
                  xmlns:xlink="http://www.w3.org/1999/xlink"
                  xlink:href="#grey-rect"
                  x="0"
                  y="0"
                />
              </svg>
              <span class="color-legend-value">unknown XLA cluster</span>
            </div>
          </div>
        </template>
        <template is="dom-if" if="[[_equals(colorBy, 'op_compatibility')]]">
          <div class="color-text">
            <div class="color-legend-row">
              <tf-graph-icon
                type="OP"
                height="16"
                fill-override="#0f9d58"
                stroke-override="#ccc"
              ></tf-graph-icon>
              <span class="color-legend-value">Valid Op</span>
            </div>
            <div class="color-legend-row">
              <tf-graph-icon
                type="OP"
                height="16"
                fill-override="#db4437"
                stroke-override="#ccc"
              ></tf-graph-icon>
              <span class="color-legend-value">Invalid Op</span>
            </div>
          </div>
        </template>
        <template is="dom-if" if="[[_statsNotNull(stats)]]">
          <div class="color-legend-row">
            <tf-graph-icon type="META" height="16" faded></tf-graph-icon>
            <span class="color-legend-value">unused substructure</span>
          </div>
        </template>
      </div>
    </div>
    <div class="legend-holder">
      <paper-icon-button
        icon="[[_getToggleLegendIcon(_legendOpened)]]"
        on-click="_toggleLegendOpen"
        class="toggle-legend-button"
      >
      </paper-icon-button>
      <span class="toggle-legend-text">
        [[_getToggleText(_legendOpened)]]
      </span>
      <iron-collapse opened="[[_legendOpened]]">
        <div>
          <table>
            <tr>
              <td><div class="title">Graph</div></td>
              <td>(* = expandable)</td>
            </tr>
            <tr>
              <td>
                <tf-graph-icon
                  type="META"
                  height="16"
                  fill-override="#d9d9d9"
                  stroke-override="#ccc"
                ></tf-graph-icon>
              </td>
              <td>
                Namespace<span class="gray">*</span>
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Encapsulates a set of nodes. Namespace is hierarchical and
                    based on scope.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <tf-graph-icon type="OP" height="16"></tf-graph-icon>
              </td>
              <td>
                OpNode
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Node that performs an operation. These nodes cannot expand.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <tf-graph-icon type="SERIES" height="16"></tf-graph-icon>
              </td>
              <td>
                Unconnected series<span class="gray">*</span>
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Sequence of numbered nodes that are not connected to each
                    other.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <tf-graph-icon
                  type="SERIES"
                  height="16"
                  vertical
                ></tf-graph-icon>
              </td>
              <td>
                Connected series<span class="gray">*</span>
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Sequence of numbered nodes that are connected to each other.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <svg class="icon">
                  <circle fill="white" stroke="#848484" cx="10" cy="10" r="5" />
                </svg>
              </td>
              <td>
                Constant
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Node that outputs a constant value.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <tf-graph-icon type="SUMMARY" height="20"></tf-graph-icon>
              </td>
              <td>
                Summary
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Node that collects data for visualization within
                    TensorBoard.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <svg
                  class="icon"
                  height="15px"
                  preserveAspectRatio="xMinYMid meet"
                  viewBox="0 0 15 15"
                >
                  <defs>
                    <marker
                      id="dataflow-arrowhead-legend"
                      fill="#bbb"
                      markerWidth="10"
                      markerHeight="10"
                      refX="9"
                      refY="5"
                      orient="auto-start-reverse"
                    >
                      <path d="M 0,0 L 10,5 L 0,10 C 3,7 3,3 0,0" />
                    </marker>
                  </defs>
                  <path
                    marker-end="url(#dataflow-arrowhead-legend)"
                    stroke="#bbb"
                    d="M2 9 l 29 0"
                    stroke-linecap="round"
                  />
                </svg>
              </td>
              <td>
                Dataflow edge
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Edge showing the data flow between operations. Edges flow
                    upwards unless arrowheads specify otherwise.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <svg
                  class="icon"
                  height="15px"
                  preserveAspectRatio="xMinYMid meet"
                  viewBox="0 0 15 15"
                >
                  <path
                    stroke="#bbb"
                    d="M2 9 l 29 0"
                    stroke-linecap="round"
                    stroke-dasharray="2, 2"
                  />
                </svg>
              </td>
              <td>
                Control dependency edge
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Edge showing the control dependency between operations.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
            <tr>
              <td>
                <svg
                  class="icon"
                  height="15px"
                  preserveAspectRatio="xMinYMid meet"
                  viewBox="0 0 15 15"
                >
                  <defs>
                    <marker
                      id="reference-arrowhead-legend"
                      fill="#FFB74D"
                      markerWidth="10"
                      markerHeight="10"
                      refX="9"
                      refY="5"
                      orient="auto-start-reverse"
                    >
                      <path d="M 0,0 L 10,5 L 0,10 C 3,7 3,3 0,0" />
                    </marker>
                  </defs>
                  <path
                    marker-end="url(#reference-arrowhead-legend)"
                    stroke="#FFB74D"
                    d="M2 9 l 29 0"
                    stroke-linecap="round"
                  />
                </svg>
              </td>
              <td>
                Reference edge
                <div class="legend-clarifier">
                  <span>?</span>
                  <paper-tooltip
                    animation-delay="0"
                    position="right"
                    offset="0"
                  >
                    Edge showing that the outgoing operation node can mutate the
                    incoming tensor.
                  </paper-tooltip>
                </div>
              </td>
            </tr>
          </table>
        </div>
      </iron-collapse>
    </div>
  </template>
</dom-module>

<script src="tf-graph-controls.js"></script>
